// This is a part of the WceUi library.
// Copyright (C) WceUi Team
// All rights reserved.
//
// Coded by Hui Xu
//
#pragma once
#include "WceUiLayer.h"
#include "wceui.h"

class CWceUiScrThumb;
class CWceUiScrPage;
class CWceUiScrBtn;
class CWceUiScroll;

class CWceUiScrThumb :	public CWceUiLayer
{
	friend class CWceUiScrPage;
	friend class CWceUiScroll;
	WCEUI_DYNCREATE_BEGIN(CWceUiScrThumb, CWceUiLayer)
public:
	CWceUiScrThumb(void);
	virtual ~CWceUiScrThumb(void);

	enum THUMB_TYPE
	{
		E_H_THUMB = 1,
		E_V_THUMB,
		E_THUMB_UNKNOWN,
	};

	//if thumb is read-only, it can not be moved by mouse
	void SetReadOnly(BOOL bReadOnly);
	BOOL IsReadOnly() const;

	//normal style
	void	SetNormalStyleName(LPCTSTR pNoramlStyleName);
	LPCTSTR GetNoramlStyleName() const;

	//the style when use drag the thumb
	void	SetDragStyleName(LPCTSTR pDragStyleName);
	LPCTSTR GetDragStyleName() const;

protected:
	virtual void SetProperties(PCWceUiXmlElem pCreateElem);
	virtual void OnLButtonDown(UINT nFlags,  POINT point);
	virtual void OnLButtonUp(UINT nFlags,	 POINT point);
	virtual void OnMouseMove(UINT nFlags,	 POINT point);
	virtual void OnLoseCapture();
	virtual void OnDraw(CWceUiGenericBitmap* pWndBitmap, RECT rcNeedDraw);

private:
	CWceUiScroll* GetScroll();

	void EnableHMove(BOOL bMove);
	void EnableVMove(BOOL bMove);

	void SetHLimit(int nMin, int nMax);
	void SetVLimit(int nMin, int nMax);

	int GetMinX() const;
	int GetMaxX() const;
	int GetMinY() const;
	int GetMaxY() const;

	void OnCmdMove();
	void OnCmdUp();

	void DoMove(CPoint pt);
	void MoveToPoint(CPoint pt);

	void SetThumbType(); //set the type of thumb according to parent type
	void OnRelease(POINT point, BOOL bLButtonUp);
private:
	BOOL		m_bCanHMove;
	BOOL		m_bCanVMove;

	int			m_nMinX;
	int			m_nMaxX;
	int			m_nMinY;
	int			m_nMaxY;

	THUMB_TYPE	m_thumbType;
	TCHAR		m_pDragStyleName[MAX_TAG_NAME_LEN];
	TCHAR		m_pNoramlStyleName[MAX_TAG_NAME_LEN];

	CPoint		m_lastPoint;
	BOOL		m_bMouseDown;
	BOOL		m_bReadOnly;

	CWceUiScroll* m_pScroll;
private:
	CWceUiScrThumb (const CWceUiScrThumb  &);
	CWceUiScrThumb & operator=(const CWceUiScrThumb &);
};
WCEUI_DYNCREATE_END(CWceUiScrThumb, CWceUiLayer)


//////////////////////////////////////////////////////////////////////////
/////////////////////////////CWceUiScrPage////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class CWceUiScrPage : public CWceUiLayer
{
	WCEUI_DYNCREATE_BEGIN(CWceUiScrPage, CWceUiLayer)
public:
	CWceUiScrPage(void);
	virtual ~CWceUiScrPage(void);

	enum SCROLL_PAGE_TYPE
	{
		E_H_PAGE = 1,
		E_V_PAGE,
		E_PAGE_UNKNOWN,
	};

	enum POS_TYPE
	{
		X_PAGE = 1,
		X_POS,
	};

	void SetReadOnly(BOOL bReadOnly);
	BOOL IsReadOnly() const;

	void SetStepType(POS_TYPE ePosType);
	POS_TYPE GetStepType() const;

protected:
	virtual void OnLButtonDown(UINT nFlags, POINT point);
	virtual void SetProperties(PCWceUiXmlElem pCreateElem);

private:
	CWceUiScroll* GetScroll();

	void SetPageType();	//set the page type according to the parent's type
	void SendCommand(POINT ptCursor);

private:
	SCROLL_PAGE_TYPE m_PageType;
	POS_TYPE		 m_posType;
	BOOL			 m_bFirstDraw;
	BOOL			 m_bReadOnly;
	CWceUiScroll*	 m_pScroll;

private:
	CWceUiScrPage (const CWceUiScrPage &);
	CWceUiScrPage & operator=(const CWceUiScrPage &);
};

WCEUI_DYNCREATE_END(CWceUiScrPage, CWceUiLayer)


//////////////////////////////////////////////////////////////////////////
//////////////////////////////CWceUiScrBtn////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class CWceUiScrBtn : public CWceUiLayer
{
	WCEUI_DYNCREATE_BEGIN(CWceUiScrBtn, CWceUiLayer)
public:
	CWceUiScrBtn(void);
	virtual ~CWceUiScrBtn(void);
	
	virtual void OnLButtonDown(UINT nFlags,  POINT point);
	virtual void OnLButtonUp(UINT nFlags,	 POINT point);

	virtual void SetProperties(PCWceUiXmlElem pCreateElem);
	virtual void OnTimer(WORD wIDEvent);
	virtual void OnLoseCapture();

public:
	enum SCROLL_BTN_TYPE
	{
		E_BTN_UP = 1,
		E_BTN_DOWN,
		E_BTN_LEFT,
		E_BTN_RIGHT,
		E_BTN_UNKNOWN,
	};

	enum STEP_TYPE
	{
		E_LINE = 1,
		E_PAGE,
	};

	void SetBtnType(SCROLL_BTN_TYPE eBtnType);
	SCROLL_BTN_TYPE GetBtnType() const;

	void SetStepType(STEP_TYPE eStepType);
	STEP_TYPE GetStepType() const;

	LPCTSTR GetNoramlStyleName() const;
	void	SetNormalStyleName(LPCTSTR pNoramlStyleName);

	LPCTSTR GetDownStyleName() const;
	void	SetDownStyleName(LPCTSTR pDownStyleName);

	//user is pressing the button
	BOOL	IsCommanding() const;
	
	void	UpdateDownStyleImmediately(BOOL bImmediately);

private:
	CWceUiScroll* GetScroll();
	void SendCommand();
	void OnRelease();
private:
	TCHAR			m_pNoramlStyleName[MAX_TAG_NAME_LEN];
	TCHAR			m_pDownStyleName[MAX_TAG_NAME_LEN];
	STEP_TYPE		m_StepType;
	BOOL			m_bLMouseDown;
	SCROLL_BTN_TYPE m_BtnType;
	BOOL			m_bFirstTimer;
	BOOL			m_bCommanding;
	CWceUiScroll*   m_pScroll;
	BOOL			m_bUpdateDownStyleImmediately;

private:
	CWceUiScrBtn (const CWceUiScrBtn &);
	CWceUiScrBtn& operator=(const CWceUiScrBtn &);
};
WCEUI_DYNCREATE_END(CWceUiScrBtn, CWceUiLayer)

//////////////////////////////////////////////////////////////////////////
//////////////////////////////CWceUiScroll////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class CWceUiScroll : public CWceUiLayer
{
	WCEUI_DYNCREATE_BEGIN(CWceUiScroll, CWceUiLayer)
public:
	CWceUiScroll(void);
	virtual ~CWceUiScroll(void);
	
public:
	typedef enum eSCROLL_TYPE
	{
		H_SCROLL = 1,
		V_SCROLL,
		SCROLL_UNKNOWN,
	}SCROLL_TYPE;

	CWceUiScrThumb* GetThumb();
	CWceUiScrPage*	GetPage();

	CWceUiScrBtn*	GetBtnLeft();
	CWceUiScrBtn*	GetBtnRight();
	CWceUiScrBtn*	GetBtnUp();
	CWceUiScrBtn*	GetBtnDown();
	
	void SetReadOnly(BOOL bReadOnly);

public:
	//lpsi, the new SCROLLINFO, can not be null
	//bUpdateThumb, update the thumb position
	void SetScrollInfo(LPCSCROLLINFO lpsi, BOOL bUpdateThumb = TRUE);
	//get scroll info
	const SCROLLINFO& GetScrollInfo() const;
	//get the scroll position according to the thumb position
	int GetThumbScrollPos();

	//if it doesn't need a scroll bar, the scroll will be hide or not
	void EnableAutoHide(BOOL bAutoHide);
	BOOL IsAutoHide() const;

	void SetScrollType(SCROLL_TYPE eScrollType);
	SCROLL_TYPE	GetScrollType();

	//the minimum thumb length
	//the minimum length must > 0 and <= page width (h scroll) or height (v scroll)
	void SetThumbMinLength(int nMinLength);
	int  GetThumbMinLength();

	//VScr
	void OnScrPageUp();
	void OnScrPageDown();
	void OnScrVTrack();
	void OnScrVEndScroll();
	void OnScrLineUp();
	void OnScrLineDown();

	//HScr
	void OnScrPageLeft();
	void OnScrPageRight();
	void OnScrHTrack();
	void OnScrHEndScroll();
	void OnScrLineLeft();
	void OnScrLineRight();

protected:
	virtual void SetProperties(PCWceUiXmlElem pCreateElem);

private:
	void EnableAutoSize(BOOL bAutoSize);
	BOOL IsAutoSize() const;
	void CheckAndSetAutoSize(LPCSCROLLINFO lpsi);

	BOOL IsNeedUpdateThumbInfo(const SCROLLINFO& curScrollInfo);
	BOOL IsNeedSetThumb(const SCROLLINFO& curScrollInfo);
	void Var_UpdateHThumbInfo();
	void Var_UpdateVThumbInfo();

	void Fix_UpdateHThumbInfo();	
	void Fix_UpdateVThumbInfo();	

	int impVar_GetHThumbScrollPos();
	int impVar_GetVThumbScrollPos();
	int impFix_GetHThumbScrollPos();
	int impFix_GetVThumbScrollPos();

private:
	BOOL		m_bThumbAutoSize;
	BOOL		m_bAutoHide;
	SCROLL_TYPE	m_ScrollType;

	SCROLLINFO	m_ScrollInfo;		//current scroll info
	SCROLLINFO	m_LastScrollInfo;	//last scroll info
	int			m_OldThumbPos;

	int			m_nThumbMiniLength;
	DWORD		m_dwLastTickCount;

	CWceUiScrPage*  m_pPage;
	CWceUiScrThumb* m_pThumb;
private:
	CWceUiScroll (const CWceUiScroll &);
	CWceUiScroll& operator=(const CWceUiScroll &);
};
WCEUI_DYNCREATE_END(CWceUiScroll, CWceUiLayer)